﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Draco.OWF.Studio.Common.WPF;

namespace Draco.OWF.Studio.Designer
{
    /// <summary>
    /// CoordinateCanvas.xaml
    /// </summary>
    public partial class CoordinateCanvas : Canvas
    {
        private IDesignerEnv m_Env=null;
        private IProcessDefinitionEditor m_ProcessDEditor;
        private Arrow m_DrawingArrow=null;
        private Dictionary<String, ActivityFacet> m_ActivityFacets = new Dictionary<String, ActivityFacet>();
        private Dictionary<String, RouteFacet> m_RouteFacets = new Dictionary<String, RouteFacet>();

        #region Init
        public CoordinateCanvas()
        {
            InitializeComponent();
        }
        public void InitCoordinate(IDesignerEnv env,IProcessDefinitionEditor editor)
        {
            if (env == null || editor==null)
                throw new ArgumentNullException();
            m_Env = env;
            m_ProcessDEditor = editor;
            m_Env.ActivityFacetDragAction = MoveAction.DrawRouteFacet;
        }
        #endregion

        #region Load Process/Activity/Route
        public void LoadProcess(IProcess process)
        {
            if (process != null)
            {
                foreach (IActivity Ac in process.Activities)
                {
                    AddActivityFacet(Ac);
                }
                foreach (IRoute route in process.Routes)
                {
                    AddRouteFacet(route);
                }
            }
        }

        public void AddActivityFacet(IActivity activity)
        {
            ActivityFacet ac = new ActivityFacet(activity,this, m_Env);
            m_ActivityFacets[activity.Id]=ac;
            ac.ActivityFacetMove += new ActivityFaceMoveEventHandler(ActivityFacet_Move);
            ac.DrawRouteStart += new DrawRouteEventHandler(ac_DrawRouteStart);
            ac.DrawRouteMoving += new DrawRouteEventHandler(ac_DrawRouteMoving);
            ac.DrawRouteComplete += new DrawRouteEventHandler(ac_DrawRouteComplete);
            
            Canvas.SetLeft(ac, ac.X);
            Canvas.SetTop(ac, ac.Y);
            this.Children.Add(ac);
        }
        protected void AddRouteFacet(IRoute route)
        {
            ActivityFacet acFrom = m_ActivityFacets[route.FromId];
            ActivityFacet acTo = m_ActivityFacets[route.ToId];
            if (acFrom != null && acTo != null)
            {
                RouteFacet RouteFacet = new RouteFacet(acFrom, acTo);
                m_RouteFacets[route.Id] = RouteFacet;
                this.Children.Add(RouteFacet);
            }
        }
        #endregion

        #region Draw Route

        void ac_DrawRouteStart(ActivityFacet facet, DrawRouteEventArgs e)
        {
            if (m_DrawingArrow == null)
            {
                m_DrawingArrow = new Arrow();
                m_DrawingArrow.HeadWidth = 10;
                m_DrawingArrow.HeadHeight = 5;
                m_DrawingArrow.StrokeThickness = 2;
                m_DrawingArrow.Stroke = Brushes.Black;
            }
            m_DrawingArrow.X1 = e.StartMousePoint.X;
            m_DrawingArrow.Y1 = e.StartMousePoint.Y;
            m_DrawingArrow.X2 = m_DrawingArrow.X1 + e.DeltaX;
            m_DrawingArrow.Y2 = m_DrawingArrow.Y1+ e.DeltaY;
            this.Children.Add(m_DrawingArrow);
        }
        void ac_DrawRouteMoving(ActivityFacet facet, DrawRouteEventArgs e)
        {
            if (m_DrawingArrow != null)
            {
                m_DrawingArrow.X2 = m_DrawingArrow.X2 + e.DeltaX;
                m_DrawingArrow.Y2 = m_DrawingArrow.Y2 + e.DeltaY;
            }
        }
        void ac_DrawRouteComplete(ActivityFacet facet, DrawRouteEventArgs e)
        {
            this.Children.Remove(m_DrawingArrow);
            ActivityFacet TarFacet = GetActivityFacetByPoint(e.CurrentMousePoint);
            if (TarFacet != null)
            {
                IRoute route = m_ProcessDEditor.ProcessDefinition.GetRoute(facet.Activity.Id, TarFacet.Activity.Id);
                if (route == null)
                {
                    //create new route
                    route = m_ProcessDEditor.AddRoute(facet.Activity, TarFacet.Activity);
                    AddRouteFacet(route);
                }
            }
        }
        
        #endregion
        

        private void ActivityFacet_Move(ActivityFacet face, ActivityFaceMoveEventArgs e)
        {
            Canvas.SetLeft(face, face.X);
            Canvas.SetTop(face, face.Y);
        }

        private ActivityFacet GetActivityFacetByPoint(Point p)
        {
            foreach (ActivityFacet facet in this.m_ActivityFacets.Values)
            {
                if (facet.HitTest(p))
                    return facet;
            }
            return null;
        }
    }
}
